/*
 * XMLUtils.java
 * Created on 21.08.2005
 *
 * VirtualHockey.net Internet Platform
 * Copyright (c) 2005-2006, Jan Janke
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hockeo.vhbase.utils.xml;


import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import org.xml.sax.EntityResolver;
import org.xml.sax.SAXException;

import com.hockeo.vhbase.error.GConfigurationException;

/**
 * Default implementation of the {@link IGXmlService} interface.
 * 
 * @version $Id$
 * @author jankejan
 */
public class GDefaultXMLService implements IGXmlService, ResourceLoaderAware
{
  /*
   * ================================================================================
   * Private members
   * ================================================================================
   */
  private ResourceLoader       d_resourceLoader;
  private EntityResolver       d_xmlEntityResolver;
  private GXmlStdErrorHandler d_xmlErrorHandler;

  /*
   * ================================================================================
   * Non-static methods
   * ================================================================================
   */

  /*
   * (non-Javadoc)
   * 
   * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader)
   */
  public void setResourceLoader( ResourceLoader resourceLoader )
  {
    d_resourceLoader = resourceLoader;
  }

  /**
   * Sets the XML {@link EntityResolver} to be used by this class.
   * 
   * @param schemaLoader the schemaLoader to set
   */
  public void setXmlEntityResolver( EntityResolver schemaLoader )
  {
    d_xmlEntityResolver = schemaLoader;
  }

  /**
   * Sets the {@link GXmlStdErrorHandler} to be used by this class.
   * 
   * @param xmlErrorHandler the xmlErrorHandler to set
   */
  public void setXmlErrorHandler( GXmlStdErrorHandler xmlErrorHandler )
  {
    d_xmlErrorHandler = xmlErrorHandler;
  }

  /*
   * (non-Javadoc)
   * 
   * @see vh.utils.xml.IVHXmlService#getDocument(java.lang.String, java.lang.String)
   */
  public Document getDocument( String strXmlPath, String strSchemaPath ) throws GConfigurationException
  {
    SAXReader reader = new SAXReader( true );
    Resource  resXml = d_resourceLoader.getResource( strXmlPath );

    // Use a specific resolver to be able to use the Spring ResourceLoader
    //
    reader.setEntityResolver( d_xmlEntityResolver );

    // Set error handler
    //
    reader.setErrorHandler( d_xmlErrorHandler );

    try
    {
      // Enable XML Schema validation and set the schema to validate against
      //
      reader.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema" );
      reader.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaSource", strSchemaPath );

      // Parse the document and return it
      //
      Document doc = reader.read( resXml.getURL() );

      // Check for parsing errors
      //
      if ( d_xmlErrorHandler.hasErrors() )
        throw new GConfigurationException( "XML validation errors occured while parsing " + resXml.getFilename() );

      return doc;
    }
    catch ( SAXException ex )
    {
      throw new GConfigurationException( "Error while setting XML parser properties.", ex );
    }
    catch ( DocumentException ex )
    {
      throw new GConfigurationException( "Error while parsing file " + resXml.getFilename(), ex );
    }
    catch ( IOException ex )
    {
      throw new GConfigurationException( "Error while trying to create URL for " + resXml.getFilename(), ex );
    }
  }

  /*
   * (non-Javadoc)
   * 
   * @see vh.utils.xml.IVHXmlService#getLocaleSpecificChild(org.dom4j.Element,
   *      java.lang.String, java.util.Locale)
   */
  @SuppressWarnings("unchecked")
  public Element getLocaleSpecificChild( Element parent, String strChildTagName, Locale locale )
  {
    Element first = null;

    for ( Iterator<Element> it = parent.elementIterator( strChildTagName ); it.hasNext(); )
    {
      Element child = it.next();
      if ( first == null )
        first = child;

      String strLang = child.attributeValue( XML_ATTR_LANG );
      if ( strLang != null && strLang.equalsIgnoreCase( locale.getLanguage() ) )
        return child;
    }

    return first;
  }

}
